package org.coderfun.workspace.interceptor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.persistence.EntityManager;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.beanutils.PropertyUtils;
import org.coderfun.common.exception.AppException;
import org.coderfun.common.exception.ErrorCodeEnum;
import org.coderfun.fieldmeta.auth.AuthService;
import org.coderfun.fieldmeta.common.FieldmetaErrorCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;

import klg.common.dataaccess.EntityManagerUtil;
import klg.common.utils.ReflectionTools;

public class WorkspaceInterceptor implements MethodInterceptor {

	@Autowired
	AuthService authService;

	@Autowired
	EntityManager entityManager;

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		// TODO Auto-generated method stub

		if(null == authService.getWorkspaceId()){
			throw new AppException(FieldmetaErrorCode.WORKSPACE_NOT_CREATED);
		}
		
		Object[] args = invocation.getArguments();
		Method method = invocation.getMethod();
		String methodName = method.getName();
		List<Integer> indexsOfModelAttribute = ReflectionTools.getParamsIndex(method, ModelAttribute.class);
		if (methodName.equals("add") || methodName.equals("findpage") || methodName.equals("findlist") || methodName.equals("datalist")) {
			for (Integer index : indexsOfModelAttribute) {
				PropertyUtils.setProperty(args[index], "workspaceId", authService.getWorkspaceId());
			}
		} else if (method.equals("edit")) {
			// 校验数据权限
			for (Integer index : indexsOfModelAttribute) {
				Class<?> entityClass = args[index].getClass();
				Object id = EntityManagerUtil.getIdentifier(entityManager, args[index]);
				if (validDataAuth(entityClass, id, "workspaceId")) {
					throw new AppException(ErrorCodeEnum.UNAUTHORIZED);
				} else {
					PropertyUtils.setProperty(args[index], "workspaceId", authService.getWorkspaceId());
				}
			}
		}
		if (!validDataAuth(method, args)) {
			throw new AppException(ErrorCodeEnum.UNAUTHORIZED);
		}
		return invocation.proceed();
	}

	private boolean validDataAuth(Method method, Object[] args) {
		WorkspaceValid validDataAuth = method.getAnnotation(WorkspaceValid.class);
		if (null != validDataAuth) {
			String entityIdValueArg = validDataAuth.entityIdValueArg();
			Object entityId = ReflectionTools.getArgValue(method, entityIdValueArg, args);
			return validDataAuth(validDataAuth.entityClass(), entityId, validDataAuth.entityAuthField());
		} else {
			return true;
		}
	}

	private boolean validDataAuth(Class<?> entityClass, Object entityId, String entityAuthField){
		Object entity = entityManager.find(entityClass, entityId);
		Long workspaceId = null;
		try {
			workspaceId = (Long) PropertyUtils.getProperty(entity, entityAuthField);
		} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return workspaceId.equals(authService.getWorkspaceId());
	}

}
